android: support text and link sharing - #814
Conversation
2d7aa5b to
cbda6b1
Compare
| object BrowserOpener { | ||
| // Pin the ACTION_VIEW to the user's default browser package so non-browser | ||
| // apps that also claim http(s) (e.g. the Google app) don't trigger the chooser. | ||
| fun openInDefaultBrowser(context: Context, uri: Uri): Boolean { |
There was a problem hiding this comment.
should we restrict to http/https uris?
There was a problem hiding this comment.
I updated slightly to let this handle both http/https and any supported protocol:
Tested, functional
- http:, https:, tel:, sms:, mailto:.
Tested, not yet supported, falls through to "copy" handler on tap:
tailscale:
Tested, fails & falls through to "copy" handler:
invalid:
The latter 2 could be improved slightly (i.e., we could show "copy" instead of "open" for the subtitle) if we used PackageManager.resolveActivity to preemptively check whether a URL can be handled, but as I understand it, older Android versions and some OEM flavors restrict access to that.
5598b66 to
f0f55e3
Compare
f894b47 to
57adc08
Compare
| Intent(context, InlineShareActionReceiver::class.java).apply { | ||
| action = InlineShareActionReceiver.ACTION_CONSUME | ||
| putExtra(InlineShareActionReceiver.EXTRA_KIND, pending.kind.name.lowercase()) | ||
| putExtra(InlineShareActionReceiver.EXTRA_CONTENT, pending.content) |
There was a problem hiding this comment.
what if this hits the size limit? https://developer.android.com/guide/components/activities/parcelables-and-bundles#sdbp looks like this is 1MB
There was a problem hiding this comment.
Good catch, I wasn't familiar with that. Updated to send and ref by ID.
6f3fa7c to
31569a6
Compare
kari-ts
left a comment
There was a problem hiding this comment.
thanks for bearing with me!
| InlineShare.Kind.URL -> openUrl(context, item.share.content) | ||
| InlineShare.Kind.TEXT -> copyToClipboard(context, item.share.content) | ||
| } | ||
| Notifier.removeInlineShare(item.share.id) |
There was a problem hiding this comment.
it looks like copyToClipboard returns if there is a failure. should we still call removeInlineShare in this case?
There was a problem hiding this comment.
I'll make copyToClipboard return Boolean and gate removeInlineShare +
TaildropNotifier.cancel on it. Same for openUrl, since it falls back to the clipboard.
Also wrapping setPrimaryClip in runCatching. It can throw out of consume().
|
|
||
| private fun encryptedPrefs() = (UninitializedApp.get() as App).getEncryptedPrefs() | ||
|
|
||
| fun save(inbox: List<PendingInlineShare>) { |
There was a problem hiding this comment.
do we have a size bound on inbox before persisting? I wonder if a large taildrop or a bunch of pending saves might make this synchronous save problematic (cause lags, performance issues)
There was a problem hiding this comment.
No bound today, afaik, and thinking about why led somewhere bigger.
I'd been assuming this path only sees modest text selections and URLs, since that's what the share sheet produces. But routing is by filename, not origin, so anything named md5.txt lands here. Someone taildropping a hash-named log dump would hit this path and get it silently converted into a clipboard snippet instead of a saved file. That's a real (if specific) use case we'd be breaking and it's a better argument than any size cap. So rather than bound the ephemeral path, I've removed it. Details below.
- Share sheet text/link sharing is unchanged, here and in the open iOS PR.
<md5>.txtand<md5>.urlsave to the Taildrop folder like any other file. This does block text/link sharing until a folder is picked, but that's consistent with every other share and it deletes a lot of code..urlfiles are deleted on either "open link" or dismiss. Android has no handler for the format and I legitimately can't think of a reason to keep one lingering on your phone..txtfiles are never deleted. Copy is offered when the file is small enough to be worth reading back; otherwise it's just a file. Anyone already sending themselves<md5>.txtlog dumps is unaffected.
There was a problem hiding this comment.
hmmm this is probably even more niche but if we get a .url file and the user dismisses the banner then the file gets deleted right? probably obscure enough that it is very unlikely to happen but just wanted to clarify
There was a problem hiding this comment.
Yes, in the latest revision, that dismiss action removes the .url file & users would need to reshare it. On mobile, this seems like a reasonable trade off to avoid a pile of unusable .url files.
iOS actually does support .webloc, but even there, it seems awkward to persist those files. I updated its PR to behave the same as Android does here.
This enhances the Android share feature as follows: - Text and URLs will be recognized and shared via the .txt and .url files - Files, text, and URLs will now show a small banner atop the devices list, mirroring iOS behavior. - If multiple taildrops arrive, tapping the banner will open a bottom sheet to take action on them individually. - Files can be opened or the enclosing taildrop folder opened. - Text can be copied. - URLs can be opened in the default browser. - "Recently Used" taildrop targets will be locally cached and presented atop the list. Presentation & max length matches iOS behavior. - Simple polling for online status is added to avoid the need to reload the share sheet to find devices that connect while it is visible. - Fixes a bug that can cause the share sheet to be non-functional if you share; don't exit the view; share again The iOS and macOS share extensions are currently receiving minor Taildrop enhancements to support sharing of Text and URLs from the OS-level share menu. To allow older clients to seamlessly receive shares from newer clients, the .txt and .url suffixes were chosen. iOS & macOS (in tailscale/corp#44001), Android (with these changes), and soon Windows and Linux will recognize these file types and respond accordingly upon receipt of them: - .txt: Notification presented to "copy" the text to the clipboard. - .url: Notification presented to "open" the link For platforms that lack in-app notifications, the files will additionally be saved to the Taildrop folder as "Text [timestamp].txt", "URL [timestamp].inetloc", or "URL [timestamp].url". This addresses a limitation for users who explicitly opt-out of app notifications. Those users would otherwise receive no transferred content whatsoever. Upon use or dismissal of URL shares, the .url file will be deleted. This is done to avoid piling up generally unusable .url files on Android in the Taildrop folder. All other taildrop file transfer functionality remain unchanged. updates tailscale/tailscale#4896 updates tailscale/tailscale#4996 fixes tailscale/tailscale#16850 Signed-off-by: Will Hannah <willh@tailscale.com>
31569a6 to
53a231e
Compare
This enhances the Android share feature as follows:
The iOS and macOS share extensions are currently receiving minor
Taildrop enhancements to support sharing of Text and URLs from
the OS-level share menu. To allow older clients to seamlessly receive
shares from newer clients, the .txt and .url suffixes were chosen.
iOS & macOS (in https://github.com/tailscale/corp/pull/44001), Android
(with these changes), and soon Windows and Linux will recognize these
file types and respond accordingly upon receipt of them:
For platforms that lack in-app notifications, the files will additionally
be saved to the Taildrop folder as "Text [timestamp].txt",
"URL [timestamp].inetloc", or "URL [timestamp].url". This addresses
a limitation for users who explicitly opt-out of app notifications. Those
users would otherwise receive no transferred content whatsoever.
Upon use or dismissal of URL shares, the .url file will be deleted. This
is done to avoid piling up generally unusable .url files on Android in the
Taildrop folder.
All other taildrop file transfer functionality remain unchanged.
updates tailscale/tailscale#4896
updates tailscale/tailscale#4996
fixes tailscale/tailscale#16850